Introduction

1. Data Description

1.1. Sample Selected

You can define bullet list or numbered list:

  • Pizza
  • Pasta
  • Cafe
    • Espresso
    • Macchiato
    • Cappuccino
  • Vodka
    • Bisont Grass
    • Soplica

1.2. Formula

Here you can define formula

\[ y = \beta_0 + \beta_1X + \epsilon \] the formula can be reported in the text: \(\mu = 1/n \sum X_i\)

1.3. Import Data (CSV) [*]

data_SD3 <- read.delim("~/RProjects/2024-Q2-R-2 [MDA2024, exercises]/D1_SD3/data_SD3.csv", stringsAsFactors=TRUE)

[ 1.3. BONUS ]

  • Imported:
    • Forbes2000.csv
    • glass.csv
Forbes2000 <- read.csv("~/RProjects/2024-Q2-R-2 [MDA2024, exercises]/D0_Data/Forbes2000.csv", stringsAsFactors=TRUE)
glass <- read.csv("~/RProjects/2024-Q2-R-2 [MDA2024, exercises]/D0_Data/glass.csv", stringsAsFactors=TRUE)

2. Data Analysis

To add R code in the Notebook we need to use the Chunk.

X <- iris

It is possible to have an overview of the data by using the summary function.

summary(X)
  Sepal.Length    Sepal.Width     Petal.Length  
 Min.   :4.300   Min.   :2.000   Min.   :1.000  
 1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.600  
 Median :5.800   Median :3.000   Median :4.350  
 Mean   :5.843   Mean   :3.057   Mean   :3.758  
 3rd Qu.:6.400   3rd Qu.:3.300   3rd Qu.:5.100  
 Max.   :7.900   Max.   :4.400   Max.   :6.900  
  Petal.Width          Species  
 Min.   :0.100   setosa    :50  
 1st Qu.:0.300   versicolor:50  
 Median :1.300   virginica :50  
 Mean   :1.199                  
 3rd Qu.:1.800                  
 Max.   :2.500                  

In R there are three main type of data:

Y <- as.matrix(X[ ,1:4])

To handle data you can use the following code:

X[10, 2]       # selection of one element in the Data Frame (or matrix)
[1] 3.1
X[5:20, 1:3]   # selection of an interval
X[5:20, ]      # the empty space select all the columns or rows
X$Sepal.Length # the symbol $ is used to select a column in the data frame
  [1] 5.1 4.9 4.7 4.6 5.0 5.4 4.6 5.0 4.4 4.9 5.4 4.8 4.8
 [14] 4.3 5.8 5.7 5.4 5.1 5.7 5.1 5.4 5.1 4.6 5.1 4.8 5.0
 [27] 5.0 5.2 5.2 4.7 4.8 5.4 5.2 5.5 4.9 5.0 5.5 4.9 4.4
 [40] 5.1 5.0 4.5 4.4 5.0 5.1 4.8 5.1 4.6 5.3 5.0 7.0 6.4
 [53] 6.9 5.5 6.5 5.7 6.3 4.9 6.6 5.2 5.0 5.9 6.0 6.1 5.6
 [66] 6.7 5.6 5.8 6.2 5.6 5.9 6.1 6.3 6.1 6.4 6.6 6.8 6.7
 [79] 6.0 5.7 5.5 5.5 5.8 6.0 5.4 6.0 6.7 6.3 5.6 5.5 5.5
 [92] 6.1 5.8 5.0 5.6 5.7 5.7 6.2 5.1 5.7 6.3 5.8 7.1 6.3
[105] 6.5 7.6 4.9 7.3 6.7 7.2 6.5 6.4 6.8 5.7 5.8 6.4 6.5
[118] 7.7 7.7 6.0 6.9 5.6 7.7 6.3 6.7 7.2 6.2 6.1 6.4 7.2
[131] 7.4 7.9 6.4 6.3 6.1 7.7 6.3 6.4 6.0 6.9 6.7 6.9 5.8
[144] 6.8 6.7 6.7 6.3 6.5 6.2 5.9

2.1. Plots in R

boxplot(X$Sepal.Length, main = "Box Plot of the Sepal Length of the IRIS Flowers", col = "blue", horizontal = T)
Error in if (horizontal) plot.window(ylim = xlim, xlim = ylim, log = log,  : 
  the condition has length > 1

The elements of the box-plot are reported below:

  • Q1. It is the First Quartile. It leaves 25% of units on the left and 75% of units on the right. Left side of the box
  • Me. It is the Median=Q2. It leaves 50% of units on left and right. Bold Line in the middle of the box
  • Q3. It is the Third Quartile. It leaves 75% of the units on the left and 25% of the units on the right. Right side of the box
  • In case of no outliers, the whiskers are defined as:
    • Xmin is the left whiskers
    • Xmax is the right whiskers
  • In case of outliers, the whiskers are defined as:
    • Linf = Q1 - 1.5 (Q3-Q1): Lower Limit
    • Lsup = Q1 + 1.5 (Q3-Q1): Upper Limit
# just a boxplot
boxplot(X[ ,1:4])

# boxplot with a title and colors
boxplot(X[ ,1:4], main = "Box Plot of all quantitative variables of IRIS data", col = terrain.colors(4))

boxplot(X$Sepal.Width ~ X$Species, main = "Box Plot of Sepal Width considering the 3 types of flowers", xlab = "Type of IRIS Flowers", ylab = "Sepal Width", col = terrain.colors(4))

The tilde symbol is obtained by:

  • these doesn’t work [*]:
    • MAC: option + 5
    • WIN: ALT + 125/6
  • these works [*]:
    • MAC: shift + button before no.1
    • WIN: shift + button before no.1

[ 2.1. BONUS ]

The bold line is the Median, that is the value of the ordered distribution that leaves the same number of units above and below (or on left and right)

  • Q1 is the first quartile. Q1 leaves 25% of unirs on left and 75% on right.
  • Q3 is the third quartile. Q3 leaves 75% of units on left and 25% on right.
  • Wishers, without outliers are, the min and max of distribution
  • Wishers, with outliers are, Lmin = Q1-1.5(Q3-Q1); Lsup = Q3+1.5(Q3-Q1);
boxplot(X$Sepal.Length, main = "Box-Plot of the Sepal Lenght", col = "green", horizontal = F)

boxplot(X[ ,1:4], main = "Box-Plot with all the Variables", col = "blue", horizontal = F)

boxplot(X$Sepal.Width ~ X$Species, main = "Box-Plot about Sepal Width with different type of IRIS Flowers")

2.2. Bar Plot

Bar Plot can be used for Qualitative Data and for Categorized Quantitative Data. The first step to create a Bar Plot is to generate a Table of Frequency.

T <- table(X$Species)
T

    setosa versicolor  virginica 
        50         50         50 
barplot(T, main = "Bar Plot of Type of flowers", xlab = "Type of flowers", ylab = "Absolute Frequency", col = terrain.colors(4))

2.3. Pie Chart

It is based on the frequency table.

pie(T, main = "Pie Chart", col = terrain.colors(4))

2.4. Histogram Chart

Histogram is a plot used only for Quantitative Data, it is based on a frequency tables in classes. The R function is called hist and the input is a simple distribution of a quantitative variable.

hist(X$Sepal.Length)

hist(X$Sepal.Width, main = "Histogram of Sepal Width", xlab = "Classes", ylab = "Absolute Frequency", col = "lightgreen", border = "blue")

[ 2.4. BONUS ]

he histogram can be used only for quantitative variables.

hist(X$Sepal.Width, main = "Histogram of the Sepal Width", xlab = "Classes",
     ylab = "Absolute Frequency", col = "green", border = "red", breaks = 10)

In case of equally spaced (same size) classes we can report on the Y axis the Absolute Frequency or relative frequency. In case of classes with different sizes we have to report on Y axis the density of frequency. The formula is the following: \(d_i = n_i/h_i\), where \(n_i\) is the absolute frequency and \(h_i\) is the size of the class.

3. Correlation Analysis

3.1. Correlation Plot

plot(X$Sepal.Length, X$Sepal.Width, main = "Correlation Plot", xlab = "Sepal Length", ylab = "Sepal Width")

[ 3.1. BONUS ]

plot(X$Petal.Length, X$Petal.Width, main = "Correlation Plot",
     xlab = "Petal Lenght", ylab = "Petal Width", col = "blue",
     pch = 1)

Plots with IRIS

plot(X$Sepal.Length, X$Sepal.Width, main = "(1-2) Plot with IRIS", 
     xlab = "Sepal Lenght", ylab = "Sepal Width", col = "blue")

plot(X$Petal.Length, X$Petal.Width, main = "(2-2) Plot with IRIS", 
     xlab = "Petal Lenght", ylab = "Petal Width", col = "red")

3.2. Pair Plot

pairs(X[ ,1:4])

The plots below the main diagonal are the same of the plot above the main diagonal. The reason is because the plot and the correlation index are symmetric.

r <- cor(X[ ,1:2])
r <- round(r, 3)
r
             Sepal.Length Sepal.Width
Sepal.Length        1.000      -0.118
Sepal.Width        -0.118       1.000
cor(X$Sepal.Length, X$Sepal.Width)
[1] -0.1175698

The range of correlation index is: -1 <= r <= 1 The interpretation of the Correlation Index called r is following:

  • 0.00 < |r| <= 0.25 Low Correlation
  • 0.25 < |r| <= 0.50 Medium-Low Correlation
  • 0.50 < |r| <= 0.75 Medium-High Correlation
  • 0.75 < |r| <= 1.00 High Correlation
  • 0 No Correlation
  • 1 Perfect Correlation

The correlation between Sepal Length and Sepal Width is -0.118 and it is a low negative correlation.

4. Plots with GGPLOT Package

install.packages("ggplot2")
Error in install.packages : Updating loaded packages
library(ggplot2)

GGPLOTS has 3 main arguments:

# GGPLOT (example no 1)
ggplot(data = X[ ,1:2])

# GGPLOT (example no 2.1)
ggplot(data = X[ ,1:2]) +
  geom_point(mapping = aes(X$Sepal.Length, X$Sepal.Width))

# GGPLOT (example no 2.2)
ggplot(data = X[ ,1:2]) +
  geom_point(mapping = aes(Sepal.Length, Sepal.Width))

# GGPLOT (example no 2.2)
ggplot(data = X) +
  geom_point(mapping = aes(Sepal.Length, Sepal.Width))

# GGPLOT (example no 3)
ggplot(data = X) +
  geom_point(mapping = aes(Sepal.Length, Sepal.Width)) +
  ggtitle("Scatter Plot") + xlab("Sepal Length") + ylab("Sepal Width")

4.1. Correlation Plot (Scatter Plot) with colors

ggplot(data = X) +
  geom_point(mapping = aes(Sepal.Length, Sepal.Width, color = Species))

[ 4.1. BONUS ]

STANDARD TEMPLATE IS: ggplot(data = ) + (mapping = aes())

# First Example
ggplot(data = X) + 
  geom_point(mapping = aes(Petal.Length, Petal.Width, color = Species)) +
  ggtitle("Petal Lenght and Width") +
  xlab("Petal Lenght") + ylab("Petal Width")

# Second Example
ggplot(data = X, mapping = aes(Petal.Width, Petal.Length)) + 
  geom_point(mapping = aes(color = Species)) +
  ggtitle("Petal Width and Lenght") + 
  xlab("Petal Width") + ylab("Petal Lenght")

4.2. Box Plot

ggplot(data = X) +
  geom_boxplot(mapping = aes(Sepal.Width), color = "blue", outlier.colour = "red", outlier.shape = 8, outlier.size = 3) +
  ggtitle("Box Plot for Sepal Lenght")

Box Plot taking into account the 3 types of flowers

ggplot(data = X) +
  geom_boxplot(mapping = aes(Species, Sepal.Width), outlier.color = "red", outlier.shape = 8)

GGPLOT function as object

p <- ggplot(data = X) +
  geom_boxplot(mapping = aes(Species, Sepal.Width, fill = Species))
p

p + theme(legend.position = "bottom")

4.3. Bar Plot

ggplot(data = X) + 
  geom_bar(mapping = aes(Species)) + 
  ggtitle("Bar Plot with GGPLOT") + 
  ylab("Absolute Frequency")

6. Regression Model [*]

In regression model we need to define the dependent and independent variables. In our case the model is define as follow:

In the first place we need to create a scatter plot (correlation plot).

6.1. Regression Model: Plot [*]

ggplot(data = Y) +
  geom_point(mapping = aes(displ, hwy)) +
  geom_smooth(method = lm, mapping = aes(displ, hwy))
`geom_smooth()` using formula = 'y ~ x'

6.2. Regression Model: Different Plot per each group [*]

ggplot(data = Y) +
  geom_point(mapping = aes(displ, hwy, color  = drv)) +
  geom_smooth(method = lm, mapping = aes(displ, hwy, color = drv))
`geom_smooth()` using formula = 'y ~ x'

6.3. Regression Model: Parameters Estimation [*]

res.reg <- lm(hwy ~ displ, data = Y)
summary(res.reg)

Call:
lm(formula = hwy ~ displ, data = Y)

Residuals:
    Min      1Q  Median      3Q     Max 
-7.1039 -2.1646 -0.2242  2.0589 15.0105 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  35.6977     0.7204   49.55   <2e-16 ***
displ        -3.5306     0.1945  -18.15   <2e-16 ***
---
Signif. codes:  
0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.836 on 232 degrees of freedom
Multiple R-squared:  0.5868,    Adjusted R-squared:  0.585 
F-statistic: 329.5 on 1 and 232 DF,  p-value: < 2.2e-16

The regression coefficients are defined as follow:

  • \(\beta_0\) is the intercept and is the value of Y when X is equal to zero
  • \(\beta_1\) is the regression coefficient and is the slope of the line. It is the value of Y when there is a variant of X equal to 1: \(\Delta_x=1\)

6.3.1. Regression Parameters

The results of the regression model showed that the estimated \(\beta_0\) (the intercept) is equal to 35.6977 and the estimated \(\beta_1\) (the regression coefficient/slope) is equal to -3.3506.

6.3.2. Godness of Fit

The quality of the model is measured by the godness of fix index \(R^2\) that is for this case study equal to 0.585. The \(R^2\) is interpreted as follow:

  • 0.00 < \(R^2\) <= 0.25 Low Quality
  • 0.25 < \(R^2\) <= 0.50 Medium-Low Quality
  • 0.50 < \(R^2\) <= 0.75 Medium-High Quality
  • 0.75 < \(R^2\) < 1.00 High Quality
  • \(R^2\) = 0 Non connection between Y and X. The result will be on horizontal line
  • \(R^2\) = 1 Perfect connection between Y and X. The data points will be exactly on the regression line

In this case study we have a Medium-High Quality of the model.

6.3.3. Test on the estimated Regression Parameters

To test the regression parameters it is possible to use the t-value or the p-value, as reported below:

  • Approach by using the t-value:
    • -2 < t-value < 2 we accept the null hypothesis (BAD). The relation between Y and X is not statistically significant.
    • t-value > 2 we reject the null hypothesis (GOOD). The relation between Y and X is statistically significant
    • t-value < -2 we reject the null hypothesis (GOOD). The relation between Y and X is statistically significant.
  • Approach by using the p-value:
    • p-value > 0.05 (5%) we accept the null hypothesis (BAD). The relation between Y and X is not statistically significant.
    • p-value < 0.05 (5%) we reject the null hypothesis (GOOD). The relation between Y and X is statistically significant.

In this case study the estimated regression coefficient \(\beta_1\) is statistically significant, since the t-value is -18.15 (< 2) and the p-value is 2e-16 (< 5%). It means that the number of mile per gallon (hwy) depends by the power of the engine (displ), so by increasing the displ of 1 unit, the hwy will decrease by -3.5306.

7. Principal Component Analysis (PCA) [ BONUS ]

The Principal Component Analysis has the following aims and characteristics:

library(FactoMineR)
library(ggplot2)
library(factoextra)

For the PCA we will use the PCA function in the Package FactoMineR.

Y <- mpg

7.1 PCA for mpg Data

res.pca <- PCA(Y[,c(3,5,8,9)])

summary(res.pca)

Call:
PCA(X = Y[, c(3, 5, 8, 9)]) 


Eigenvalues
                       Dim.1   Dim.2   Dim.3   Dim.4
Variance               3.509   0.379   0.071   0.041
% of var.             87.736   9.477   1.772   1.014
Cumulative % of var.  87.736  97.214  98.986 100.000

Individuals (the 10 first)
          Dist    Dim.1    ctr   cos2    Dim.2    ctr
1     |  2.002 |  1.832  0.408  0.837 | -0.600  0.406
2     |  2.211 |  2.190  0.584  0.981 | -0.289  0.094
3     |  2.202 |  2.160  0.568  0.963 | -0.129  0.019
4     |  2.203 |  2.196  0.587  0.994 | -0.118  0.016
5     |  0.709 |  0.336  0.014  0.225 | -0.077  0.007
6     |  0.731 |  0.575  0.040  0.619 |  0.130  0.019
7     |  0.720 |  0.543  0.036  0.568 |  0.340  0.130
8     |  1.822 |  1.581  0.304  0.753 | -0.879  0.872
9     |  1.781 |  1.258  0.193  0.499 | -1.180  1.569
10    |  1.954 |  1.910  0.444  0.955 | -0.408  0.188
        cos2    Dim.3    ctr   cos2  
1      0.090 | -0.187  0.212  0.009 |
2      0.017 | -0.087  0.046  0.002 |
3      0.003 | -0.056  0.019  0.001 |
4      0.003 |  0.000  0.000  0.000 |
5      0.012 | -0.498  1.493  0.493 |
6      0.032 | -0.431  1.119  0.348 |
7      0.222 | -0.290  0.506  0.162 |
8      0.233 | -0.122  0.089  0.004 |
9      0.439 | -0.167  0.167  0.009 |
10     0.044 |  0.010  0.001  0.000 |

Variables
         Dim.1    ctr   cos2    Dim.2    ctr   cos2  
displ | -0.932 24.773  0.869 |  0.309 25.155  0.095 |
cyl   | -0.933 24.821  0.871 |  0.307 24.860  0.094 |
cty   |  0.951 25.754  0.904 |  0.271 19.334  0.073 |
hwy   |  0.930 24.652  0.865 |  0.341 30.652  0.116 |
       Dim.3    ctr   cos2  
displ  0.187 49.213  0.035 |
cyl   -0.183 47.082  0.033 |
cty    0.038  2.010  0.001 |
hwy   -0.035  1.694  0.001 |

7.2 PCA on mtcars

Z <- mtcars
res.pca1 <- PCA(Z)
Warning: ggrepel: 17 unlabeled data points (too many overlaps). Consider increasing max.overlaps

summary(res.pca1)

Call:
PCA(X = Z) 


Eigenvalues
                       Dim.1   Dim.2   Dim.3   Dim.4
Variance               6.608   2.650   0.627   0.270
% of var.             60.076  24.095   5.702   2.451
Cumulative % of var.  60.076  84.172  89.873  92.324
                       Dim.5   Dim.6   Dim.7   Dim.8
Variance               0.223   0.212   0.135   0.123
% of var.              2.031   1.924   1.230   1.117
Cumulative % of var.  94.356  96.279  97.509  98.626
                       Dim.9  Dim.10  Dim.11
Variance               0.077   0.052   0.022
% of var.              0.700   0.473   0.200
Cumulative % of var.  99.327  99.800 100.000

Individuals (the 10 first)
                      Dist    Dim.1    ctr   cos2  
Mazda RX4         |  2.234 | -0.657  0.204  0.087 |
Mazda RX4 Wag     |  2.081 | -0.629  0.187  0.091 |
Datsun 710        |  2.987 | -2.779  3.653  0.866 |
Hornet 4 Drive    |  2.521 | -0.312  0.046  0.015 |
Hornet Sportabout |  2.456 |  1.974  1.844  0.646 |
Valiant           |  3.014 | -0.056  0.001  0.000 |
Duster 360        |  3.187 |  3.003  4.264  0.888 |
Merc 240D         |  2.841 | -2.055  1.998  0.523 |
Merc 230          |  3.733 | -2.287  2.474  0.375 |
Merc 280          |  1.907 | -0.526  0.131  0.076 |
                   Dim.2    ctr   cos2    Dim.3    ctr
Mazda RX4          1.735  3.551  0.604 | -0.601  1.801
Mazda RX4 Wag      1.550  2.833  0.555 | -0.382  0.728
Datsun 710        -0.146  0.025  0.002 | -0.241  0.290
Hornet 4 Drive    -2.363  6.584  0.879 | -0.136  0.092
Hornet Sportabout -0.754  0.671  0.094 | -1.134  6.412
Valiant           -2.786  9.151  0.855 |  0.164  0.134
Duster 360         0.335  0.132  0.011 | -0.363  0.656
Merc 240D         -1.465  2.531  0.266 |  0.944  4.439
Merc 230          -1.984  4.639  0.282 |  1.797 16.094
Merc 280          -0.162  0.031  0.007 |  1.493 11.103
                    cos2  
Mazda RX4          0.072 |
Mazda RX4 Wag      0.034 |
Datsun 710         0.007 |
Hornet 4 Drive     0.003 |
Hornet Sportabout  0.213 |
Valiant            0.003 |
Duster 360         0.013 |
Merc 240D          0.110 |
Merc 230           0.232 |
Merc 280           0.613 |

Variables (the 10 first)
                     Dim.1    ctr   cos2    Dim.2    ctr
mpg               | -0.932 13.143  0.869 |  0.026  0.026
cyl               |  0.961 13.981  0.924 |  0.071  0.191
disp              |  0.946 13.556  0.896 | -0.080  0.243
hp                |  0.848 10.894  0.720 |  0.405  6.189
drat              | -0.756  8.653  0.572 |  0.447  7.546
wt                |  0.890 11.979  0.792 | -0.233  2.046
qsec              | -0.515  4.018  0.266 | -0.754 21.472
vs                | -0.788  9.395  0.621 | -0.377  5.366
am                | -0.604  5.520  0.365 |  0.699 18.440
gear              | -0.532  4.281  0.283 |  0.753 21.377
                    cos2    Dim.3    ctr   cos2  
mpg                0.001 | -0.179  5.096  0.032 |
cyl                0.005 | -0.139  3.073  0.019 |
disp               0.006 | -0.049  0.378  0.002 |
hp                 0.164 |  0.111  1.960  0.012 |
drat               0.200 |  0.128  2.598  0.016 |
wt                 0.054 |  0.271 11.684  0.073 |
qsec               0.569 |  0.319 16.255  0.102 |
vs                 0.142 |  0.340 18.388  0.115 |
am                 0.489 | -0.163  4.234  0.027 |
gear               0.567 |  0.229  8.397  0.053 |

7.2.1 Eigenvalues interpretation

The eigenvalues measure the level of information retained by the PCA. They show the explained variance from the data and help us to select the number of Latent Variables (or Latent Traits, Principal Components, Dimensions). The rules to select the number of LVs are: - Eigenvalues greater than 1. \(\lambda > 1\). - Cumulative percentage of explained variance > 0.7 (70%)

In our case study we select two components. Both components have eigenvalue greater than 1 and with and Cumulative percentage of explained variance equal to 84.172%.

round(res.pca1$eig,3)
        eigenvalue percentage of variance
comp 1       6.608                 60.076
comp 2       2.650                 24.095
comp 3       0.627                  5.702
comp 4       0.270                  2.451
comp 5       0.223                  2.031
comp 6       0.212                  1.924
comp 7       0.135                  1.230
comp 8       0.123                  1.117
comp 9       0.077                  0.700
comp 10      0.052                  0.473
comp 11      0.022                  0.200
        cumulative percentage of variance
comp 1                             60.076
comp 2                             84.172
comp 3                             89.873
comp 4                             92.324
comp 5                             94.356
comp 6                             96.279
comp 7                             97.509
comp 8                             98.626
comp 9                             99.327
comp 10                            99.800
comp 11                           100.000

7.2.2 Variables Plot (Variables Dimension)

Below we can read the table with correlations between the Manifest Variables (MVs) and the Latent Variables (Dimensions). The correlations are also the coordinates of the manifest variables on the variables plot.

For the interpretation:

  • Higher is the correlation(bigger is the coordinate), higher is the importance of the manifest variable for the latent variable(Dimension).
  • The sign of correlation give information about the position of the manifest variable:
    • On the first dimension: Positive sign, the MV is on the right side; Negative sign, the MV is on the left side
    • On the second dimension: Positive sign, the MV is on the upper side; Negative sign, the MV is on the lower side
  • We can give a meaning to the two Latent Variables (Dimensions) based on the correlation and the sign.

In our case study, the LVs (dimensions) are so defined:

  • \(LV_1\): Right side (cyl, disp, hp, wt); Left side (mpg, drat, vs)
  • \(LV_2\). Upper side (am, gear, carb); Lower side (qsec)
round(res.pca1$var$coord[,1:2],3)
      Dim.1  Dim.2
mpg  -0.932  0.026
cyl   0.961  0.071
disp  0.946 -0.080
hp    0.848  0.405
drat -0.756  0.447
wt    0.890 -0.233
qsec -0.515 -0.754
vs   -0.788 -0.377
am   -0.604  0.699
gear -0.532  0.753
carb  0.550  0.673

it is possible to evaluate the correlations between the manifest variables by using the angle between the vectors. For instance, the variables hp, cyl, disp and wt are all positively correlated since all the angles are less then 90°.

plot.PCA(res.pca1, axes = c(1,2), choix = "var")

The quality of the projected manifest variables is given by the Cosine squared.

Below you can find the interpretation intervals:

  • 0.00 < \(Cos^2\) <= 0.25: Low Quality
  • 0.25 < \(Cos^2\) <= 0.50: Medium-Low Quality
  • 0.50 < \(Cos^2\) <= 0.75: Medium-High Quality
  • 0.75 < \(Cos^2\) <= 1.00: High Quality
round(res.pca1$var$cos2[,1:2],3)
     Dim.1 Dim.2
mpg  0.869 0.001
cyl  0.924 0.005
disp 0.896 0.006
hp   0.720 0.164
drat 0.572 0.200
wt   0.792 0.054
qsec 0.266 0.569
vs   0.621 0.142
am   0.365 0.489
gear 0.283 0.567
carb 0.303 0.453

7.2.3 Units Plot

In the units plot we can evaluate the clusters of units. The clusters define group of units that are similar on the basis of the Latent Variables estimated.

plot.PCA(res.pca1, axes = c(1,2), choix = "ind")
Warning: ggrepel: 17 unlabeled data points (too many overlaps). Consider increasing max.overlaps

7.3 PCA with Factoextra Package

library(factoextra)

7.3.1 Variables Plot

fviz_pca_var(res.pca1)

7.3.2 Units Plot

fviz_pca_ind(res.pca1)

7.3.3 BiPlot

Biplot is a plot where both units and variables are represented.

fviz_pca_biplot(res.pca1)

7.3.4 Graphical representation of the Eigenvalues

fviz_screeplot(res.pca1)

7.3.5 Graphical representation of the Contributions of the manifest variables

fviz_pca_contrib(res.pca1, choice = "var")
Warning in fviz_pca_contrib(res.pca1, choice = "var") :
  The function fviz_pca_contrib() is deprecated. Please use the function fviz_contrib() which can handle outputs  of PCA, CA and MCA functions.

LS0tCnRpdGxlOiAiTXkgRmlyc3QgTm90ZWJvb2sgTURBMjAyNCIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyBJbnRyb2R1Y3Rpb24KCgojIDEuIERhdGEgRGVzY3JpcHRpb24KCiMjIDEuMS4gU2FtcGxlIFNlbGVjdGVkCgpZb3UgY2FuIGRlZmluZSBidWxsZXQgbGlzdCBvciBudW1iZXJlZCBsaXN0OgoKLSBQaXp6YQotIFBhc3RhCi0gQ2FmZQogIC0gRXNwcmVzc28KICAtIE1hY2NoaWF0bwogIC0gQ2FwcHVjY2lubwotIFZvZGthCiAgLSBCaXNvbnQgR3Jhc3MKICAtIFNvcGxpY2EKCiMjIDEuMi4gRm9ybXVsYQoKSGVyZSB5b3UgY2FuIGRlZmluZSBmb3JtdWxhCgokJCB5ID0gXGJldGFfMCArIFxiZXRhXzFYICsgXGVwc2lsb24gJCQKdGhlIGZvcm11bGEgY2FuIGJlIHJlcG9ydGVkIGluIHRoZSB0ZXh0OiAkXG11ID0gMS9uIFxzdW0gWF9pJAoKIyMgMS4zLiBJbXBvcnQgRGF0YSAoQ1NWKSBbKl0KCi0gUHJlLXRyYWluZWQgTW9kZWxzOgogIC0gaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9tb2RlbHMKCi0gT3BlbiBwc3ljaG9sb2d5IGRhdGEgW3JhdyBkYXRhXToKICAtIGh0dHA6Ly9vcGVucHN5Y2hvbWV0cmljcy5vcmcvX3Jhd2RhdGEvCgotIEluZm8gYWJvdXQgdXNlZCBkYXRhIFtEUy0zXToKICAtIG9wZW5wc3ljaG9tZXRyaWNzLm9yZy90ZXN0cy9TRDMvCiAgICAtIERhcmsgVHJpYWQgUGVyc29uYWxpdHkgVGVzdCBbZGF0YV0KICAgIC0gU0QtMyBzdGFuZHMgZm9yIFNob3J0IERhcmsgVHJpYWQKCmBgYHtyfQpkYXRhX1NEMyA8LSByZWFkLmRlbGltKCJ+L1JQcm9qZWN0cy8yMDI0LVEyLVItMiBbTURBMjAyNCwgZXhlcmNpc2VzXS9EMV9TRDMvZGF0YV9TRDMuY3N2Iiwgc3RyaW5nc0FzRmFjdG9ycz1UUlVFKQpgYGAKCiMjIFsgMS4zLiBCT05VUyBdCgotIEltcG9ydGVkOgogIC0gRm9yYmVzMjAwMC5jc3YKICAtIGdsYXNzLmNzdgoKYGBge3J9CkZvcmJlczIwMDAgPC0gcmVhZC5jc3YoIn4vUlByb2plY3RzLzIwMjQtUTItUi0yIFtNREEyMDI0LCBleGVyY2lzZXNdL0QwX0RhdGEvRm9yYmVzMjAwMC5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzPVRSVUUpCmBgYAoKYGBge3J9CmdsYXNzIDwtIHJlYWQuY3N2KCJ+L1JQcm9qZWN0cy8yMDI0LVEyLVItMiBbTURBMjAyNCwgZXhlcmNpc2VzXS9EMF9EYXRhL2dsYXNzLmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnM9VFJVRSkKYGBgCgojIDIuIERhdGEgQW5hbHlzaXMKVG8gYWRkIFIgY29kZSBpbiB0aGUgTm90ZWJvb2sgd2UgbmVlZCB0byB1c2UgdGhlICoqQ2h1bmsqKi4KCmBgYHtyfQpYIDwtIGlyaXMKYGBgCgpJdCBpcyBwb3NzaWJsZSB0byBoYXZlIGFuIG92ZXJ2aWV3IG9mIHRoZSBkYXRhIGJ5IHVzaW5nIHRoZSAqc3VtbWFyeSogZnVuY3Rpb24uCgpgYGB7cn0Kc3VtbWFyeShYKQpgYGAKSW4gUiB0aGVyZSBhcmUgdGhyZWUgbWFpbiB0eXBlIG9mIGRhdGE6CgotICoqTWF0cml4KiouIE1hdGhlbWF0aWNhbCBPYmplY3QuIEluIG91ciBleGFtcGxlICoqWSoqIGlzIGEgbWF0cml4LgotICoqRGF0YSBGcmFtZSoqLiBJdCBpcyBkZXZvdGVkIHRvIG9yZ2FuaXplIGFuZCBhbmFseXplIGRhdGEgYW5kIGl0IGlzIGEgZ2VuZXJhbGl6YXRpb24gb2YgdGhlIE1hdHJpeC4gSW4gb3VyIGV4YW1wbGUsICoqWCoqIGlzIGEgZGF0YSBmcmFtZS4KLSAqKkxpc3QqKi4gSXQgaXMgYW4gb2JqZWN0IHRoYXQgY2FuIGluY2x1ZGUgRGF0YSBGcmFtZXMsIE1hdHJpY2VzIG9yIG90aGVyIGxpc3RzLgoKYGBge3J9ClkgPC0gYXMubWF0cml4KFhbICwxOjRdKQpgYGAKClRvIGhhbmRsZSBkYXRhIHlvdSBjYW4gdXNlIHRoZSBmb2xsb3dpbmcgY29kZToKCmBgYHtyfQpYWzEwLCAyXSAgICAgICAjIHNlbGVjdGlvbiBvZiBvbmUgZWxlbWVudCBpbiB0aGUgRGF0YSBGcmFtZSAob3IgbWF0cml4KQpYWzU6MjAsIDE6M10gICAjIHNlbGVjdGlvbiBvZiBhbiBpbnRlcnZhbApYWzU6MjAsIF0gICAgICAjIHRoZSBlbXB0eSBzcGFjZSBzZWxlY3QgYWxsIHRoZSBjb2x1bW5zIG9yIHJvd3MKWCRTZXBhbC5MZW5ndGggIyB0aGUgc3ltYm9sICQgaXMgdXNlZCB0byBzZWxlY3QgYSBjb2x1bW4gaW4gdGhlIGRhdGEgZnJhbWUKYGBgCiMjIDIuMS4gUGxvdHMgaW4gUgoKYGBge3J9CmJveHBsb3QoWCRTZXBhbC5MZW5ndGgsIG1haW4gPSAiQm94IFBsb3Qgb2YgdGhlIFNlcGFsIExlbmd0aCBvZiB0aGUgSVJJUyBGbG93ZXJzIiwgY29sID0gImJsdWUiLCBob3Jpem9udGFsID0gVCkKYGBgClRoZSBlbGVtZW50cyBvZiB0aGUgYm94LXBsb3QgYXJlIHJlcG9ydGVkIGJlbG93OgoKLSAqKlExKiouIEl0IGlzIHRoZSAqRmlyc3QgUXVhcnRpbGUqLiBJdCBsZWF2ZXMgMjUlIG9mIHVuaXRzIG9uIHRoZSBsZWZ0IGFuZCA3NSUgb2YgdW5pdHMgb24gdGhlIHJpZ2h0LiAqTGVmdCBzaWRlIG9mIHRoZSBib3gqCi0gKipNZSoqLiBJdCBpcyB0aGUgKk1lZGlhbj1RMiouIEl0IGxlYXZlcyA1MCUgb2YgdW5pdHMgb24gbGVmdCBhbmQgcmlnaHQuICpCb2xkIExpbmUgaW4gdGhlIG1pZGRsZSBvZiB0aGUgYm94KgotICoqUTMqKi4gSXQgaXMgdGhlICpUaGlyZCBRdWFydGlsZSouIEl0IGxlYXZlcyA3NSUgb2YgdGhlIHVuaXRzIG9uIHRoZSBsZWZ0IGFuZCAyNSUgb2YgdGhlIHVuaXRzIG9uIHRoZSByaWdodC4gKlJpZ2h0IHNpZGUgb2YgdGhlIGJveCoKLSBJbiBjYXNlIG9mICoqbm8gb3V0bGllcnMqKiwgdGhlIHdoaXNrZXJzIGFyZSBkZWZpbmVkIGFzOgogIC0gKipYbWluKiogaXMgdGhlIGxlZnQgd2hpc2tlcnMKICAtICoqWG1heCoqIGlzIHRoZSByaWdodCB3aGlza2VycwotIEluIGNhc2Ugb2YgKipvdXRsaWVycyoqLCB0aGUgd2hpc2tlcnMgYXJlIGRlZmluZWQgYXM6CiAgLSAqKkxpbmYqKiA9IFExIC0gMS41IChRMy1RMSk6IExvd2VyIExpbWl0CiAgLSAqKkxzdXAqKiA9IFExICsgMS41IChRMy1RMSk6IFVwcGVyIExpbWl0CiAgCmBgYHtyfQojIGp1c3QgYSBib3hwbG90CmJveHBsb3QoWFsgLDE6NF0pCiMgYm94cGxvdCB3aXRoIGEgdGl0bGUgYW5kIGNvbG9ycwpib3hwbG90KFhbICwxOjRdLCBtYWluID0gIkJveCBQbG90IG9mIGFsbCBxdWFudGl0YXRpdmUgdmFyaWFibGVzIG9mIElSSVMgZGF0YSIsIGNvbCA9IHRlcnJhaW4uY29sb3JzKDQpKQpgYGAKICAKYGBge3J9CmJveHBsb3QoWCRTZXBhbC5XaWR0aCB+IFgkU3BlY2llcywgbWFpbiA9ICJCb3ggUGxvdCBvZiBTZXBhbCBXaWR0aCBjb25zaWRlcmluZyB0aGUgMyB0eXBlcyBvZiBmbG93ZXJzIiwgeGxhYiA9ICJUeXBlIG9mIElSSVMgRmxvd2VycyIsIHlsYWIgPSAiU2VwYWwgV2lkdGgiLCBjb2wgPSB0ZXJyYWluLmNvbG9ycyg0KSkKYGBgCgpUaGUgKnRpbGRlIHN5bWJvbCogaXMgb2J0YWluZWQgYnk6CgotIHRoZXNlIGRvZXNuJ3Qgd29yayBbKl06CiAgLSBNQUM6IG9wdGlvbiArIDUKICAtIFdJTjogQUxUICsgMTI1LzYKLSB0aGVzZSB3b3JrcyBbKl06CiAgLSBNQUM6IHNoaWZ0ICsgYnV0dG9uIGJlZm9yZSBuby4xCiAgLSBXSU46IHNoaWZ0ICsgYnV0dG9uIGJlZm9yZSBuby4xCgojIyBbIDIuMS4gQk9OVVMgXQoKVGhlIGJvbGQgbGluZSBpcyB0aGUgKipNZWRpYW4qKiwgdGhhdCBpcyB0aGUgdmFsdWUgb2YgdGhlIG9yZGVyZWQgZGlzdHJpYnV0aW9uIHRoYXQgbGVhdmVzIHRoZSBzYW1lIG51bWJlciBvZiB1bml0cyBhYm92ZSBhbmQgYmVsb3cgKG9yIG9uIGxlZnQgYW5kIHJpZ2h0KQoKLSAqKlExKiogaXMgdGhlIGZpcnN0IHF1YXJ0aWxlLiBRMSBsZWF2ZXMgMjUlIG9mIHVuaXJzIG9uIGxlZnQgYW5kIDc1JSBvbiByaWdodC4KLSAqKlEzKiogaXMgdGhlIHRoaXJkIHF1YXJ0aWxlLiBRMyBsZWF2ZXMgNzUlIG9mIHVuaXRzIG9uIGxlZnQgYW5kIDI1JSBvbiByaWdodC4KLSBXaXNoZXJzLCAqKndpdGhvdXQgb3V0bGllcnMqKiBhcmUsIHRoZSBtaW4gYW5kIG1heCBvZiBkaXN0cmlidXRpb24KLSBXaXNoZXJzLCAqKndpdGggb3V0bGllcnMqKiBhcmUsIExtaW4gPSBRMS0xLjUqKFEzLVExKTsgTHN1cCA9IFEzKzEuNSooUTMtUTEpOwoKYGBge3J9CmJveHBsb3QoWCRTZXBhbC5MZW5ndGgsIG1haW4gPSAiQm94LVBsb3Qgb2YgdGhlIFNlcGFsIExlbmdodCIsIGNvbCA9ICJncmVlbiIsIGhvcml6b250YWwgPSBGKQpib3hwbG90KFhbICwxOjRdLCBtYWluID0gIkJveC1QbG90IHdpdGggYWxsIHRoZSBWYXJpYWJsZXMiLCBjb2wgPSAiYmx1ZSIsIGhvcml6b250YWwgPSBGKQpib3hwbG90KFgkU2VwYWwuV2lkdGggfiBYJFNwZWNpZXMsIG1haW4gPSAiQm94LVBsb3QgYWJvdXQgU2VwYWwgV2lkdGggd2l0aCBkaWZmZXJlbnQgdHlwZSBvZiBJUklTIEZsb3dlcnMiKQpgYGAKCiMjIDIuMi4gQmFyIFBsb3QKCkJhciBQbG90IGNhbiBiZSB1c2VkIGZvciAqKlF1YWxpdGF0aXZlIERhdGEqKiBhbmQgZm9yICoqQ2F0ZWdvcml6ZWQgUXVhbnRpdGF0aXZlIERhdGEqKi4gVGhlIGZpcnN0IHN0ZXAgdG8gY3JlYXRlIGEgQmFyIFBsb3QgaXMgdG8gZ2VuZXJhdGUgYSAqVGFibGUgb2YgRnJlcXVlbmN5Ki4KCmBgYHtyfQpUIDwtIHRhYmxlKFgkU3BlY2llcykKVApgYGAKCmBgYHtyfQpiYXJwbG90KFQsIG1haW4gPSAiQmFyIFBsb3Qgb2YgVHlwZSBvZiBmbG93ZXJzIiwgeGxhYiA9ICJUeXBlIG9mIGZsb3dlcnMiLCB5bGFiID0gIkFic29sdXRlIEZyZXF1ZW5jeSIsIGNvbCA9IHRlcnJhaW4uY29sb3JzKDQpKQpgYGAKCiMjIDIuMy4gUGllIENoYXJ0CgpJdCBpcyBiYXNlZCBvbiB0aGUgZnJlcXVlbmN5IHRhYmxlLgoKYGBge3J9CnBpZShULCBtYWluID0gIlBpZSBDaGFydCIsIGNvbCA9IHRlcnJhaW4uY29sb3JzKDQpKQpgYGAKCiMjIDIuNC4gSGlzdG9ncmFtIENoYXJ0CgpIaXN0b2dyYW0gaXMgYSBwbG90IHVzZWQgb25seSBmb3IgKipRdWFudGl0YXRpdmUgRGF0YSoqLCBpdCBpcyBiYXNlZCBvbiBhIGZyZXF1ZW5jeSB0YWJsZXMgaW4gY2xhc3Nlcy4gVGhlICpSKiBmdW5jdGlvbiBpcyBjYWxsZWQgKmhpc3QqIGFuZCB0aGUgaW5wdXQgaXMgYSBzaW1wbGUgZGlzdHJpYnV0aW9uIG9mIGEgcXVhbnRpdGF0aXZlIHZhcmlhYmxlLgoKYGBge3J9Cmhpc3QoWCRTZXBhbC5MZW5ndGgpCmBgYAoKYGBge3J9Cmhpc3QoWCRTZXBhbC5XaWR0aCwgbWFpbiA9ICJIaXN0b2dyYW0gb2YgU2VwYWwgV2lkdGgiLCB4bGFiID0gIkNsYXNzZXMiLCB5bGFiID0gIkFic29sdXRlIEZyZXF1ZW5jeSIsIGNvbCA9ICJsaWdodGdyZWVuIiwgYm9yZGVyID0gImJsdWUiKQpgYGAKCiMjIFsgMi40LiBCT05VUyBdCgpoZSBoaXN0b2dyYW0gY2FuIGJlIHVzZWQgb25seSBmb3IgKipxdWFudGl0YXRpdmUgdmFyaWFibGVzKiouIAoKYGBge3J9Cmhpc3QoWCRTZXBhbC5XaWR0aCwgbWFpbiA9ICJIaXN0b2dyYW0gb2YgdGhlIFNlcGFsIFdpZHRoIiwgeGxhYiA9ICJDbGFzc2VzIiwKICAgICB5bGFiID0gIkFic29sdXRlIEZyZXF1ZW5jeSIsIGNvbCA9ICJncmVlbiIsIGJvcmRlciA9ICJyZWQiLCBicmVha3MgPSAxMCkKCmBgYAoKSW4gY2FzZSBvZiBlcXVhbGx5IHNwYWNlZCAoc2FtZSBzaXplKSBjbGFzc2VzIHdlIGNhbiByZXBvcnQgb24gdGhlICpZKiBheGlzIHRoZSBBYnNvbHV0ZSBGcmVxdWVuY3kgb3IgcmVsYXRpdmUgZnJlcXVlbmN5LiBJbiBjYXNlIG9mIGNsYXNzZXMgd2l0aCBkaWZmZXJlbnQgc2l6ZXMgd2UgaGF2ZSB0byByZXBvcnQgb24gKlkqIGF4aXMgdGhlICpkZW5zaXR5IG9mIGZyZXF1ZW5jeSouIFRoZSBmb3JtdWxhIGlzIHRoZSBmb2xsb3dpbmc6ICRkX2kgPSBuX2kvaF9pJCwgd2hlcmUgJG5faSQgaXMgdGhlIGFic29sdXRlIGZyZXF1ZW5jeSBhbmQgJGhfaSQgaXMgdGhlIHNpemUgb2YgdGhlIGNsYXNzLgoKIyAzLiBDb3JyZWxhdGlvbiBBbmFseXNpcwoKIyMgMy4xLiBDb3JyZWxhdGlvbiBQbG90CgpgYGB7cn0KcGxvdChYJFNlcGFsLkxlbmd0aCwgWCRTZXBhbC5XaWR0aCwgbWFpbiA9ICJDb3JyZWxhdGlvbiBQbG90IiwgeGxhYiA9ICJTZXBhbCBMZW5ndGgiLCB5bGFiID0gIlNlcGFsIFdpZHRoIikKYGBgCgojIyBbIDMuMS4gQk9OVVMgXQoKYGBge3J9CnBsb3QoWCRQZXRhbC5MZW5ndGgsIFgkUGV0YWwuV2lkdGgsIG1haW4gPSAiQ29ycmVsYXRpb24gUGxvdCIsCiAgICAgeGxhYiA9ICJQZXRhbCBMZW5naHQiLCB5bGFiID0gIlBldGFsIFdpZHRoIiwgY29sID0gImJsdWUiLAogICAgIHBjaCA9IDEpCmBgYAoKUGxvdHMgd2l0aCBJUklTCgpgYGB7cn0KcGxvdChYJFNlcGFsLkxlbmd0aCwgWCRTZXBhbC5XaWR0aCwgbWFpbiA9ICIoMS0yKSBQbG90IHdpdGggSVJJUyIsIAogICAgIHhsYWIgPSAiU2VwYWwgTGVuZ2h0IiwgeWxhYiA9ICJTZXBhbCBXaWR0aCIsIGNvbCA9ICJibHVlIikKcGxvdChYJFBldGFsLkxlbmd0aCwgWCRQZXRhbC5XaWR0aCwgbWFpbiA9ICIoMi0yKSBQbG90IHdpdGggSVJJUyIsIAogICAgIHhsYWIgPSAiUGV0YWwgTGVuZ2h0IiwgeWxhYiA9ICJQZXRhbCBXaWR0aCIsIGNvbCA9ICJyZWQiKQpgYGAKCiMjIDMuMi4gUGFpciBQbG90CgpgYGB7cn0KcGFpcnMoWFsgLDE6NF0pCmBgYAoKVGhlIHBsb3RzIGJlbG93IHRoZSBtYWluIGRpYWdvbmFsIGFyZSB0aGUgc2FtZSBvZiB0aGUgcGxvdCBhYm92ZSB0aGUgbWFpbiBkaWFnb25hbC4gVGhlIHJlYXNvbiBpcyBiZWNhdXNlIHRoZSBwbG90IGFuZCB0aGUgY29ycmVsYXRpb24gaW5kZXggYXJlIHN5bW1ldHJpYy4KCmBgYHtyfQpyIDwtIGNvcihYWyAsMToyXSkKciA8LSByb3VuZChyLCAzKQpyCmNvcihYJFNlcGFsLkxlbmd0aCwgWCRTZXBhbC5XaWR0aCkKCmBgYAoKVGhlIHJhbmdlIG9mIGNvcnJlbGF0aW9uIGluZGV4IGlzOiAqLTEgPD0gciA8PSAxKgpUaGUgaW50ZXJwcmV0YXRpb24gb2YgdGhlICpDb3JyZWxhdGlvbiBJbmRleCogY2FsbGVkICoqcioqIGlzIGZvbGxvd2luZzoKCi0gMC4wMCA8IHxyfCA8PSAwLjI1ICpMb3cgQ29ycmVsYXRpb24qCi0gMC4yNSA8IHxyfCA8PSAwLjUwICpNZWRpdW0tTG93IENvcnJlbGF0aW9uKgotIDAuNTAgPCB8cnwgPD0gMC43NSAqTWVkaXVtLUhpZ2ggQ29ycmVsYXRpb24qCi0gMC43NSA8IHxyfCA8PSAxLjAwICpIaWdoIENvcnJlbGF0aW9uKgotIDAgKk5vIENvcnJlbGF0aW9uKgotIDEgKlBlcmZlY3QgQ29ycmVsYXRpb24qCgpUaGUgY29ycmVsYXRpb24gYmV0d2VlbiAqU2VwYWwgTGVuZ3RoKiBhbmQgKlNlcGFsIFdpZHRoKiBpcyAtMC4xMTggYW5kIGl0IGlzIGEgbG93IG5lZ2F0aXZlIGNvcnJlbGF0aW9uLgoKIyA0LiBQbG90cyB3aXRoIEdHUExPVCBQYWNrYWdlCgpgYGB7cn0KaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpCmxpYnJhcnkoZ2dwbG90MikKYGBgCgpHR1BMT1RTIGhhcyAzIG1haW4gYXJndW1lbnRzOgoKLSBUaGUgZmlyc3QgYXJndW1lbnQgaXMgdGhlIGRhdGE6ICpnZ3Bsb3QoZGF0YSA9IFgpKi4gSXQgY3JlYXRlcyBhbiBlbXB0eSBmcmFtZS4KLSBUaGUgc2Vjb25kIGFyZ3VtZW50IGlzIHRoZSBnZW9tZXRyeSAodHlwZSBvZiBwbG90KTogKmdlb21fKi4gSXQgYWRkcyBhIGxheWVyIHdpdGggdGhlIHR5cGUgb2YgcGxvdCB3ZSB3YW50IHRvIHNob3cuCi0gVGhlIHRoaXJkIGFyZ3VtZW50IGlzIHRoZSBhZXN0aGV0aWMsIHRvIHNlbGVjdCB0aGUgdmFyaWFibGVzIGFuZCB0aGUgcHJvcGVydGllczogKm1hcHBpbmcgPSBhZXMoKSoKCmBgYHtyfQojIEdHUExPVCAoZXhhbXBsZSBubyAxKQpnZ3Bsb3QoZGF0YSA9IFhbICwxOjJdKQojIEdHUExPVCAoZXhhbXBsZSBubyAyLjEpCmdncGxvdChkYXRhID0gWFsgLDE6Ml0pICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoWCRTZXBhbC5MZW5ndGgsIFgkU2VwYWwuV2lkdGgpKQojIEdHUExPVCAoZXhhbXBsZSBubyAyLjIpCmdncGxvdChkYXRhID0gWFsgLDE6Ml0pICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoU2VwYWwuTGVuZ3RoLCBTZXBhbC5XaWR0aCkpCiMgR0dQTE9UIChleGFtcGxlIG5vIDIuMikKZ2dwbG90KGRhdGEgPSBYKSArCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKFNlcGFsLkxlbmd0aCwgU2VwYWwuV2lkdGgpKQojIEdHUExPVCAoZXhhbXBsZSBubyAzKQpnZ3Bsb3QoZGF0YSA9IFgpICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoU2VwYWwuTGVuZ3RoLCBTZXBhbC5XaWR0aCkpICsKICBnZ3RpdGxlKCJTY2F0dGVyIFBsb3QiKSArIHhsYWIoIlNlcGFsIExlbmd0aCIpICsgeWxhYigiU2VwYWwgV2lkdGgiKQpgYGAKCiMjIDQuMS4gQ29ycmVsYXRpb24gUGxvdCAoU2NhdHRlciBQbG90KSB3aXRoIGNvbG9ycwoKYGBge3J9CmdncGxvdChkYXRhID0gWCkgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhTZXBhbC5MZW5ndGgsIFNlcGFsLldpZHRoLCBjb2xvciA9IFNwZWNpZXMpKQpgYGAKCiMjIFsgNC4xLiBCT05VUyBdCgoqKlNUQU5EQVJEIFRFTVBMQVRFIElTOioqCiAgZ2dwbG90KGRhdGEgPSA8REFUQT4pICsgCiAgPEdFT01fRlVOQ1RJT04+KG1hcHBpbmcgPSBhZXMoPE1BUFBJTkdTPikpCgpgYGB7cn0KIyBGaXJzdCBFeGFtcGxlCmdncGxvdChkYXRhID0gWCkgKyAKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoUGV0YWwuTGVuZ3RoLCBQZXRhbC5XaWR0aCwgY29sb3IgPSBTcGVjaWVzKSkgKwogIGdndGl0bGUoIlBldGFsIExlbmdodCBhbmQgV2lkdGgiKSArCiAgeGxhYigiUGV0YWwgTGVuZ2h0IikgKyB5bGFiKCJQZXRhbCBXaWR0aCIpCiMgU2Vjb25kIEV4YW1wbGUKZ2dwbG90KGRhdGEgPSBYLCBtYXBwaW5nID0gYWVzKFBldGFsLldpZHRoLCBQZXRhbC5MZW5ndGgpKSArIAogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhjb2xvciA9IFNwZWNpZXMpKSArCiAgZ2d0aXRsZSgiUGV0YWwgV2lkdGggYW5kIExlbmdodCIpICsgCiAgeGxhYigiUGV0YWwgV2lkdGgiKSArIHlsYWIoIlBldGFsIExlbmdodCIpCmBgYAoKIyMgNC4yLiBCb3ggUGxvdAoKYGBge3J9CmdncGxvdChkYXRhID0gWCkgKwogIGdlb21fYm94cGxvdChtYXBwaW5nID0gYWVzKFNlcGFsLldpZHRoKSwgY29sb3IgPSAiYmx1ZSIsIG91dGxpZXIuY29sb3VyID0gInJlZCIsIG91dGxpZXIuc2hhcGUgPSA4LCBvdXRsaWVyLnNpemUgPSAzKSArCiAgZ2d0aXRsZSgiQm94IFBsb3QgZm9yIFNlcGFsIExlbmdodCIpCmBgYAoKQm94IFBsb3QgdGFraW5nIGludG8gYWNjb3VudCB0aGUgMyB0eXBlcyBvZiBmbG93ZXJzCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBYKSArCiAgZ2VvbV9ib3hwbG90KG1hcHBpbmcgPSBhZXMoU3BlY2llcywgU2VwYWwuV2lkdGgpLCBvdXRsaWVyLmNvbG9yID0gInJlZCIsIG91dGxpZXIuc2hhcGUgPSA4KQpgYGAKCkdHUExPVCBmdW5jdGlvbiBhcyBvYmplY3QKCmBgYHtyfQpwIDwtIGdncGxvdChkYXRhID0gWCkgKwogIGdlb21fYm94cGxvdChtYXBwaW5nID0gYWVzKFNwZWNpZXMsIFNlcGFsLldpZHRoLCBmaWxsID0gU3BlY2llcykpCnAKcCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQpgYGAKCiMjIDQuMy4gQmFyIFBsb3QKCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IFgpICsgCiAgZ2VvbV9iYXIobWFwcGluZyA9IGFlcyhTcGVjaWVzKSkgKyAKICBnZ3RpdGxlKCJCYXIgUGxvdCB3aXRoIEdHUExPVCIpICsgCiAgeWxhYigiQWJzb2x1dGUgRnJlcXVlbmN5IikKYGBgCgojIDUuIFVzZSB0aGUgbXBnIGRhdGEgKG1wZyBGdWVsIGVjb25vbXkgZGF0YSBmcm9tIDE5OTkgdG8gMjAwOCBmb3IgMzggcG9wdWxhciBtb2RlbCBvZiBjYXJzKQoKQSBkYXRhIGZyYW1lIHdpdGggMjM0IHJvd3MgYW5kIDExIHZhcmlhYmxlczoKCi0gKm1hbnVmYWN0dXJlciogYnJhbmQgbmFtZQotICptb2RlbCogbW9kZWwgbmFtZQotICpkaXNwbCogZW5naW5lIGRpc3BsYWNlbWVudCwgaW4gbGl0cmVzIChwb3dlciBvZiB0aGUgZW5naW5lKQotICp5ZWFyKiB5ZWFyIG9mIG1hbnVmYWN0dXJlCi0gKmN5bCogbnVtYmVyIG9mIGN5bGluZGVycwotICp0cmFucyogdHlwZSBvZiB0cmFuc21pc3Npb24KLSAqZHJ2KiB0aGUgdHlwZSBvZiBkcml2ZSB0cmFpbiwgd2hlcmUgZiA9IGZyb250LXdoZWVsIGRyaXZlLCByID0gcmVhciB3aGVlbCBkcml2ZSwgNCA9IDR3ZAotICpjdHkqIGNpdHkgbWlsZXMgcGVyIGdhbGxvbiAoa20gcGVyIGxpdGVyIGluIHRvd24pCi0gKmh3eSogaGlnaHdheSBtaWxlcyBwZXIgZ2FsbG9uIChrbSBwZXIgbGl0ZXIgaW4gaGlnaHdheSkKLSAqZmwqIGZ1ZWwgdHlwZQotICpjbGFzcyogInR5cGUiIG9mIGNhcgoKYGBge3J9ClkgPC0gbXBnCmBgYAoKYGBge3J9CnN1bW1hcnkoWSkKaGVhZChZKQpgYGAKCiMjIDUuMS4gQmFyIENoYXJ0CgpgYGB7cn0KdGFibGUoWSRjeWwpCmBgYAoKYGBge3J9CiMgZmlyc3QgZXhhbXBsZTogZmFjdG9yKGN5bCkgYXMgYSBjb2xvciAoIHZlcnRpY2FsIGJhciBjaGFydCApCmdncGxvdChkYXRhID0gWSkgKwogIGdlb21fYmFyKG1hcHBpbmcgPSBhZXMoY3lsLCBmaWxsID0gZmFjdG9yKGN5bCkpKQojIHNlY29uZCBleGFtcGxlOiBjbGFzcyBhcyBhIGNvbG9yICggdmVydGljYWwgYmFyIGNoYXJ0ICkKZ2dwbG90KGRhdGEgPSBZKSArCiAgZ2VvbV9iYXIobWFwcGluZyA9IGFlcyhjeWwsIGZpbGwgPSBjbGFzcykpCiMgdGhpcmQgZXhhbXBsZTogY2xhc3MgaW5zdGVhZCBjeWwgKCB2ZXJ0aWNhbCBiYXIgY2hhcnQgKQpnZ3Bsb3QoZGF0YSA9IFkpICsKICBnZW9tX2JhcihtYXBwaW5nID0gYWVzKGN5bCwgZmlsbCA9IGNsYXNzKSkKIyBmb3VydGggZXhhbXBsZTogY2xhc3MgaW5zdGVhZCBjeWwgKCBob3Jpem9udGFsIGJhciBjaGFydCApCmdncGxvdChkYXRhID0gWSkgKwogIGdlb21fYmFyKG1hcHBpbmcgPSBhZXMoY3lsLCBmaWxsID0gY2xhc3MpKSArIGNvb3JkX2ZsaXAoKQojIGZpZnRoIGV4YW1wbGU6IGNsYXNzIGluc3RlYWQgY3lsICggaG9yaXpvbnRhbCBiYXIgY2hhcnQgJiBsZWdlbmQgYXQgdGhlIGJvdHRvbSApCmdncGxvdChkYXRhID0gWSkgKwogIGdlb21fYmFyKG1hcHBpbmcgPSBhZXMoY3lsLCBmaWxsID0gY2xhc3MpKSArIGNvb3JkX2ZsaXAoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQpgYGAKCiMjIDUuMi4gSGlzdG9ncmFtCgpgYGB7cn0KIyBleGFtcGxlIG5vIDEuMQpnZ3Bsb3QoZGF0YSA9IFkpICsKICBnZW9tX2hpc3RvZ3JhbShtYXBwaW5nID0gYWVzKGN0eSkpCiMgZXhhbXBsZSBubyAxLjIKZ2dwbG90KGRhdGEgPSBZKSArCiAgZ2VvbV9oaXN0b2dyYW0obWFwcGluZyA9IGFlcyhjdHksIGNvbG91ciA9IGNsYXNzKSkKIyBleGFtcGxlIG5vIDEuMwpnZ3Bsb3QoZGF0YSA9IFkpICsKICBnZW9tX2hpc3RvZ3JhbShtYXBwaW5nID0gYWVzKGN0eSwgZmlsbCA9IGNsYXNzKSkKIyBleGFtcGxlIG5vIDEuNApnZ3Bsb3QoZGF0YSA9IFkpICsKICBnZW9tX2hpc3RvZ3JhbShtYXBwaW5nID0gYWVzKGN0eSwgZmlsbCA9ICJyZWQiKSkKIyBleGFtcGxlIG5vIDEuNQpnZ3Bsb3QoZGF0YSA9IFkpICsKICBnZW9tX2hpc3RvZ3JhbShtYXBwaW5nID0gYWVzKGN0eSwgZmlsbCA9IGZhY3RvcihjdHkpKSkKIyBleGFtcGxlIDIKZ2dwbG90KGRhdGEgPSBZKSArCiAgZ2VvbV9oaXN0b2dyYW0obWFwcGluZyA9IGFlcyhod3kpKQpgYGAKCiMjIDUuMy4gRmFjZXQgV3JhcCB3aXRoIDEgZ3J1cCB2YXJpYWJsZSBbKl0KCldpdGggRmFjZXQgV3JhcCBsYXllciAob3B0aW9uKSB3ZSBjYW4gY3JlYXRlIHN1Yi1wbG90cyBiYXNlZCBvbiBhIGNhdGVnb3JpY2FsIHZhcmlhYmxlLgoKYGBge3J9CmdncGxvdChkYXRhID0gWSkgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhkaXNwbCwgaHd5KSkgKwogIGZhY2V0X3dyYXAofmRydikKYGBgCgojIyA1LjQuIEZhY2V0IFdyYXAgd2l0aCAyIGdydXAgdmFyaWFibGVzIFsqXQoKYGBge3J9CmdncGxvdChkYXRhID0gWSkgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhkaXNwbCwgaHd5KSkgKwogIGZhY2V0X3dyYXAoZHJ2IH4gY2xhc3MpCmBgYAoKIyMgNS41LiBTbW9vdGluZyBQbG90IFsqXQoKYGBge3J9CmdncGxvdChkYXRhID0gWSkgKwogIGdlb21fc21vb3RoKG1hcHBpbmcgPSBhZXMoZGlzcGwsIGh3eSkpCmBgYAoKIyMjIDUuNS4xLiBTbW9vdGluZyBQbG90IHdpdGggImRpZmZlcmVudCB0eXBlIG9mIGxpbmUiIFsqXQoKYGBge3J9CiMgRmlyc3QgRXhhbXBsZQpnZ3Bsb3QoZGF0YSA9IFkpICsKICBnZW9tX3Ntb290aChtYXBwaW5nID0gYWVzKGRpc3BsLCBod3ksIGxpbmV0eXBlID0gY2xhc3MpKQojIFNlY29uZCBFeGFtcGxlCmdncGxvdChkYXRhID0gWSkgKwogIGdlb21fc21vb3RoKG1hcHBpbmcgPSBhZXMoZGlzcGwsIGh3eSwgbGluZXR5cGUgPSBkcnYpKQpgYGAKCiMjIyA1LjUuMi4gU21vb3RpbmcgUGxvdCB3aXRoICJGYWNldCBXcmFwIiBbKl0KCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IFkpICsKICBnZW9tX3Ntb290aChtYXBwaW5nID0gYWVzKGRpc3BsLCBod3kpKSArCiAgZmFjZXRfd3JhcCh+IGRydikKYGBgCgojIyMgNS41LjMuIFNtb290aW5nIFBsb3Qgd2l0aCAiY29sb3IiIFsqXQoKYGBge3J9CmdncGxvdChkYXRhID0gWSkgKwogIGdlb21fc21vb3RoKG1hcHBpbmcgPSBhZXMoZGlzcGwsIGh3eSwgY29sb3IgPSBkcnYpKQpgYGAKCiMjIyA1LjUuNC4gU21vb3RpbmcgUGxvdCB3aXRoICJncm91cCIgWypdCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBZKSArCiAgZ2VvbV9zbW9vdGgobWFwcGluZyA9IGFlcyhkaXNwbCwgaHd5LCBncm91cCA9IGRydikpCmBgYAoKIyMjIDUuNS41LiBTbW9vdGluZyBQbG90IGNvbWJpbmluZyBkaWZmZXJlbnQgbGF5ZXJzIFsqXQoKYGBge3J9CmdncGxvdChkYXRhID0gWSkgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhkaXNwbCwgaHd5LCBjb2xvciA9IGRydikpICsKICBnZW9tX3Ntb290aChtYXBwaW5nID0gYWVzKGRpc3BsLCBod3ksIGNvbG9yID0gZHJ2KSkKYGBgCgojIDYuIFJlZ3Jlc3Npb24gTW9kZWwgWypdCgpJbiByZWdyZXNzaW9uIG1vZGVsIHdlIG5lZWQgdG8gZGVmaW5lIHRoZSAqZGVwZW5kZW50KiBhbmQgKmluZGVwZW5kZW50KiB2YXJpYWJsZXMuIEluIG91ciBjYXNlIHRoZSBtb2RlbCBpcyBkZWZpbmUgYXMgZm9sbG93OgoKLSAqWShEZXBlbmRlbnQvT3V0Y29tZSBWYXJpYWJsZSkqID0gKipod3kqKi4gVGhlIHZhcmlhYmxlIGRlZmluZXMgdGhlIG51bWJlciBvZiBtaWxlcyAoa20pIHBlciBHYWxsb24gKGxpdGVyKSBvbiB0aGUgaGlnaHdheS4KLSAqWChJbmRlcGVuZGVudC9JbnB1dCBWYXJpYWJsZSkqID0gKipkaXNwbCoqLiBUaGUgdmFyaWFibGUgZGVmaW5lcyB0aGUgcG93ZXIgb2YgdGhlIGVuZ2luZSAoaG9yc2UgcG93ZXIpLgoKSW4gdGhlIGZpcnN0IHBsYWNlIHdlIG5lZWQgdG8gY3JlYXRlIGEgc2NhdHRlciBwbG90IChjb3JyZWxhdGlvbiBwbG90KS4KCiMjIDYuMS4gUmVncmVzc2lvbiBNb2RlbDogUGxvdCBbKl0KCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IFkpICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoZGlzcGwsIGh3eSkpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSBsbSwgbWFwcGluZyA9IGFlcyhkaXNwbCwgaHd5KSkKYGBgCgojIyA2LjIuIFJlZ3Jlc3Npb24gTW9kZWw6IERpZmZlcmVudCBQbG90IHBlciBlYWNoIGdyb3VwIFsqXQoKYGBge3J9CmdncGxvdChkYXRhID0gWSkgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhkaXNwbCwgaHd5LCBjb2xvciAgPSBkcnYpKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gbG0sIG1hcHBpbmcgPSBhZXMoZGlzcGwsIGh3eSwgY29sb3IgPSBkcnYpKQpgYGAKCiMjIDYuMy4gUmVncmVzc2lvbiBNb2RlbDogUGFyYW1ldGVycyBFc3RpbWF0aW9uIFsqXQoKYGBge3J9CnJlcy5yZWcgPC0gbG0oaHd5IH4gZGlzcGwsIGRhdGEgPSBZKQpzdW1tYXJ5KHJlcy5yZWcpCmBgYApUaGUgcmVncmVzc2lvbiBjb2VmZmljaWVudHMgYXJlIGRlZmluZWQgYXMgZm9sbG93OgoKLSAkXGJldGFfMCQgaXMgdGhlIGludGVyY2VwdCBhbmQgaXMgdGhlIHZhbHVlIG9mICpZKiB3aGVuICpYKiBpcyBlcXVhbCB0byB6ZXJvCi0gJFxiZXRhXzEkIGlzIHRoZSByZWdyZXNzaW9uIGNvZWZmaWNpZW50IGFuZCBpcyB0aGUgc2xvcGUgb2YgdGhlIGxpbmUuIEl0IGlzIHRoZSB2YWx1ZSBvZiAqWSogd2hlbiB0aGVyZSBpcyBhIHZhcmlhbnQgb2YgKlgqIGVxdWFsIHRvIDE6ICRcRGVsdGFfeD0xJAoKIyMjIDYuMy4xLiBSZWdyZXNzaW9uIFBhcmFtZXRlcnMKClRoZSByZXN1bHRzIG9mIHRoZSByZWdyZXNzaW9uIG1vZGVsIHNob3dlZCB0aGF0IHRoZSAqZXN0aW1hdGVkKiAkXGJldGFfMCQgKHRoZSBpbnRlcmNlcHQpIGlzIGVxdWFsIHRvICoqMzUuNjk3NyoqIGFuZCB0aGUgZXN0aW1hdGVkICRcYmV0YV8xJCAodGhlIHJlZ3Jlc3Npb24gY29lZmZpY2llbnQvc2xvcGUpIGlzIGVxdWFsIHRvICoqLTMuMzUwNioqLgoKIyMjIDYuMy4yLiBHb2RuZXNzIG9mIEZpdAoKVGhlIHF1YWxpdHkgb2YgdGhlIG1vZGVsIGlzIG1lYXN1cmVkIGJ5IHRoZSBnb2RuZXNzIG9mIGZpeCBpbmRleCAkUl4yJCB0aGF0IGlzIGZvciB0aGlzIGNhc2Ugc3R1ZHkgZXF1YWwgdG8gKiowLjU4NSoqLiBUaGUgJFJeMiQgaXMgaW50ZXJwcmV0ZWQgYXMgZm9sbG93OgoKLSAwLjAwIDwgJFJeMiQgPD0gMC4yNSBMb3cgUXVhbGl0eQotIDAuMjUgPCAkUl4yJCA8PSAwLjUwIE1lZGl1bS1Mb3cgUXVhbGl0eQotIDAuNTAgPCAkUl4yJCA8PSAwLjc1IE1lZGl1bS1IaWdoIFF1YWxpdHkKLSAwLjc1IDwgJFJeMiQgPCAxLjAwIEhpZ2ggUXVhbGl0eQotICRSXjIkID0gMCBOb24gY29ubmVjdGlvbiBiZXR3ZWVuICpZKiBhbmQgKlgqLiBUaGUgcmVzdWx0IHdpbGwgYmUgb24gaG9yaXpvbnRhbCBsaW5lCi0gJFJeMiQgPSAxIFBlcmZlY3QgY29ubmVjdGlvbiBiZXR3ZWVuICpZKiBhbmQgKlgqLiBUaGUgZGF0YSBwb2ludHMgd2lsbCBiZSBleGFjdGx5IG9uIHRoZSByZWdyZXNzaW9uIGxpbmUKCkluIHRoaXMgY2FzZSBzdHVkeSB3ZSBoYXZlIGEgTWVkaXVtLUhpZ2ggUXVhbGl0eSBvZiB0aGUgbW9kZWwuCgojIyMgNi4zLjMuIFRlc3Qgb24gdGhlIGVzdGltYXRlZCBSZWdyZXNzaW9uIFBhcmFtZXRlcnMKClRvIHRlc3QgdGhlIHJlZ3Jlc3Npb24gcGFyYW1ldGVycyBpdCBpcyBwb3NzaWJsZSB0byB1c2UgdGhlICp0LXZhbHVlKiBvciB0aGUgKnAtdmFsdWUqLCBhcyByZXBvcnRlZCBiZWxvdzoKCi0gQXBwcm9hY2ggYnkgdXNpbmcgdGhlICp0LXZhbHVlKjoKICAtIC0yIDwgKnQtdmFsdWUqIDwgMiB3ZSBhY2NlcHQgdGhlIG51bGwgaHlwb3RoZXNpcyAoQkFEKS4gVGhlIHJlbGF0aW9uIGJldHdlZW4gKlkqIGFuZCAqWCogaXMgKipub3Qgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCoqLgogIC0gKnQtdmFsdWUqID4gMiB3ZSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyAoR09PRCkuIFRoZSByZWxhdGlvbiBiZXR3ZWVuICpZKiBhbmQgKlgqIGlzICoqc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCoqCiAgLSAqdC12YWx1ZSogPCAtMiB3ZSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyAoR09PRCkuIFRoZSByZWxhdGlvbiBiZXR3ZWVuICpZKiBhbmQgKlgqIGlzICoqc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCoqLgotIEFwcHJvYWNoIGJ5IHVzaW5nIHRoZSAqcC12YWx1ZSo6CiAgLSAqcC12YWx1ZSogPiAwLjA1ICg1JSkgd2UgYWNjZXB0IHRoZSBudWxsIGh5cG90aGVzaXMgKEJBRCkuIFRoZSByZWxhdGlvbiBiZXR3ZWVuICpZKiBhbmQgKlgqIGlzICoqbm90IHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQqKi4KICAtICpwLXZhbHVlKiA8IDAuMDUgKDUlKSB3ZSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyAoR09PRCkuIFRoZSByZWxhdGlvbiBiZXR3ZWVuICpZKiBhbmQgKlgqIGlzICoqc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCoqLgoKSW4gdGhpcyBjYXNlIHN0dWR5IHRoZSBlc3RpbWF0ZWQgcmVncmVzc2lvbiBjb2VmZmljaWVudCAkXGJldGFfMSQgaXMgKipzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50KiosIHNpbmNlIHRoZSAqdC12YWx1ZSogaXMgKiotMTguMTUqKiAoPCAyKSBhbmQgdGhlICpwLXZhbHVlKiBpcyAqKjJlLTE2KiogKDwgNSUpLgpJdCBtZWFucyB0aGF0IHRoZSAqbnVtYmVyIG9mIG1pbGUgcGVyIGdhbGxvbiogKGh3eSkgZGVwZW5kcyBieSB0aGUgKnBvd2VyIG9mIHRoZSBlbmdpbmUqIChkaXNwbCksIHNvIGJ5IGluY3JlYXNpbmcgdGhlICpkaXNwbCogb2YgMSB1bml0LCB0aGUgKmh3eSogd2lsbCBkZWNyZWFzZSBieSAqKi0zLjUzMDYqKi4KCiMgNy4gUHJpbmNpcGFsIENvbXBvbmVudCBBbmFseXNpcyAoUENBKSBbIEJPTlVTIF0KClRoZSBQcmluY2lwYWwgQ29tcG9uZW50IEFuYWx5c2lzIGhhcyB0aGUgZm9sbG93aW5nIGFpbXMgYW5kIGNoYXJhY3RlcmlzdGljczoKCi0gUENBIGlzIG9ubHkgZm9yICoqUXVhbnRpdGF0aXZlIERBVEEqKgotIERhdGEgUmVkdWN0aW9uIGJ5IGNyZWF0aW5nIGEgbmV3IHNldCBvZiBMYXRlbnQgVmFyaWFibGVzIGluIGEgbnVtYmVyICpxKiA8ICpwKiwgd2hlcmUgKnAqIGlzIHRoZSB0aGUgbnVtZXIgb2YgdGhlIG1hbmlmZXN0L29yaWdpbmFsIHZhcmlhYmxlcy4KLSBEaXNjb3ZlciAqTGF0ZW50IFRyYWl0cyovKkxhdGVudCBWYXJpYWJsZXMqIGluIHRoZSBkYXRhLiAKCmBgYHtyfQpsaWJyYXJ5KEZhY3RvTWluZVIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShmYWN0b2V4dHJhKQpgYGAKCkZvciB0aGUgUENBIHdlIHdpbGwgdXNlIHRoZSAqUENBKiBmdW5jdGlvbiBpbiB0aGUgUGFja2FnZSAqRmFjdG9NaW5lUiouCgpgYGB7cn0KWSA8LSBtcGcKYGBgCgojIyA3LjEgUENBIGZvciBtcGcgRGF0YQoKYGBge3J9CnJlcy5wY2EgPC0gUENBKFlbLGMoMyw1LDgsOSldKQpzdW1tYXJ5KHJlcy5wY2EpCmBgYAoKIyMgNy4yIFBDQSBvbiBtdGNhcnMKCmBgYHtyfQpaIDwtIG10Y2FycwpgYGAKCmBgYHtyfQpyZXMucGNhMSA8LSBQQ0EoWikKc3VtbWFyeShyZXMucGNhMSkKYGBgCgojIyMgNy4yLjEgRWlnZW52YWx1ZXMgaW50ZXJwcmV0YXRpb24gCgpUaGUgKmVpZ2VudmFsdWVzKiBtZWFzdXJlIHRoZSBsZXZlbCBvZiBpbmZvcm1hdGlvbiByZXRhaW5lZCBieSB0aGUgUENBLiBUaGV5IHNob3cgdGhlICpleHBsYWluZWQgdmFyaWFuY2UqIGZyb20gdGhlIGRhdGEgYW5kIGhlbHAgdXMgdG8gc2VsZWN0IHRoZSBudW1iZXIgb2YgKkxhdGVudCBWYXJpYWJsZXMqIChvciBMYXRlbnQgVHJhaXRzLCBQcmluY2lwYWwgQ29tcG9uZW50cywgRGltZW5zaW9ucykuIApUaGUgcnVsZXMgdG8gc2VsZWN0IHRoZSBudW1iZXIgb2YgTFZzIGFyZToKLSBFaWdlbnZhbHVlcyBncmVhdGVyIHRoYW4gMS4gJFxsYW1iZGEgPiAxJC4KLSBDdW11bGF0aXZlIHBlcmNlbnRhZ2Ugb2YgZXhwbGFpbmVkIHZhcmlhbmNlID4gMC43ICg3MCUpCgpJbiBvdXIgY2FzZSBzdHVkeSB3ZSBzZWxlY3QgdHdvIGNvbXBvbmVudHMuIEJvdGggY29tcG9uZW50cyBoYXZlIGVpZ2VudmFsdWUgZ3JlYXRlciB0aGFuIDEgYW5kIHdpdGggYW5kIEN1bXVsYXRpdmUgcGVyY2VudGFnZSBvZiBleHBsYWluZWQgdmFyaWFuY2UgZXF1YWwgdG8gODQuMTcyJS4KCmBgYHtyfQpyb3VuZChyZXMucGNhMSRlaWcsMykKYGBgCgojIyMgNy4yLjIgVmFyaWFibGVzIFBsb3QgKFZhcmlhYmxlcyBEaW1lbnNpb24pCgpCZWxvdyB3ZSBjYW4gcmVhZCB0aGUgdGFibGUgd2l0aCAqKmNvcnJlbGF0aW9ucyoqIGJldHdlZW4gdGhlIE1hbmlmZXN0IFZhcmlhYmxlcyAoTVZzKSBhbmQgdGhlIExhdGVudCBWYXJpYWJsZXMgKERpbWVuc2lvbnMpLiBUaGUgY29ycmVsYXRpb25zIGFyZSBhbHNvIHRoZSAqKmNvb3JkaW5hdGVzKiogb2YgdGhlIG1hbmlmZXN0IHZhcmlhYmxlcyBvbiB0aGUgdmFyaWFibGVzIHBsb3QuCgpGb3IgdGhlIGludGVycHJldGF0aW9uOgoKLSBIaWdoZXIgaXMgdGhlIGNvcnJlbGF0aW9uKGJpZ2dlciBpcyB0aGUgY29vcmRpbmF0ZSksIGhpZ2hlciBpcyB0aGUgaW1wb3J0YW5jZSBvZiB0aGUgbWFuaWZlc3QgdmFyaWFibGUgZm9yIHRoZSBsYXRlbnQgdmFyaWFibGUoRGltZW5zaW9uKS4KLSBUaGUgKipzaWduIG9mIGNvcnJlbGF0aW9uKiogZ2l2ZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgcG9zaXRpb24gb2YgdGhlIG1hbmlmZXN0IHZhcmlhYmxlOgogICsgT24gdGhlICpmaXJzdCBkaW1lbnNpb24qOiBQb3NpdGl2ZSBzaWduLCB0aGUgTVYgaXMgb24gdGhlIHJpZ2h0IHNpZGU7IE5lZ2F0aXZlIHNpZ24sIHRoZSBNViBpcyBvbiB0aGUgbGVmdCBzaWRlCiAgKyBPbiB0aGUgKnNlY29uZCBkaW1lbnNpb24qOiBQb3NpdGl2ZSBzaWduLCB0aGUgTVYgaXMgb24gdGhlIHVwcGVyIHNpZGU7IE5lZ2F0aXZlIHNpZ24sIHRoZSBNViBpcyBvbiB0aGUgbG93ZXIgc2lkZQotIFdlIGNhbiBnaXZlIGEgbWVhbmluZyB0byB0aGUgdHdvIExhdGVudCBWYXJpYWJsZXMgKERpbWVuc2lvbnMpIGJhc2VkIG9uIHRoZSBjb3JyZWxhdGlvbiBhbmQgdGhlIHNpZ24uCgpJbiBvdXIgY2FzZSBzdHVkeSwgdGhlIExWcyAoZGltZW5zaW9ucykgYXJlIHNvIGRlZmluZWQ6CgotICRMVl8xJDogKlJpZ2h0IHNpZGUqIChjeWwsIGRpc3AsIGhwLCB3dCk7ICpMZWZ0IHNpZGUqIChtcGcsIGRyYXQsIHZzKQotICRMVl8yJC4gKlVwcGVyIHNpZGUqIChhbSwgZ2VhciwgY2FyYik7ICpMb3dlciBzaWRlKiAocXNlYykKCmBgYHtyfQpyb3VuZChyZXMucGNhMSR2YXIkY29vcmRbLDE6Ml0sMykKYGBgCgppdCBpcyBwb3NzaWJsZSB0byBldmFsdWF0ZSB0aGUgY29ycmVsYXRpb25zIGJldHdlZW4gdGhlIG1hbmlmZXN0IHZhcmlhYmxlcyBieSB1c2luZyB0aGUgYW5nbGUgYmV0d2VlbiB0aGUgdmVjdG9ycy4gRm9yIGluc3RhbmNlLCB0aGUgdmFyaWFibGVzICpocCosICpjeWwqLCAqZGlzcCogYW5kICp3dCogYXJlIGFsbCBwb3NpdGl2ZWx5IGNvcnJlbGF0ZWQgc2luY2UgYWxsIHRoZSBhbmdsZXMgYXJlIGxlc3MgdGhlbiA5MMKwLgoKYGBge3J9CnBsb3QuUENBKHJlcy5wY2ExLCBheGVzID0gYygxLDIpLCBjaG9peCA9ICJ2YXIiKQpgYGAKClRoZSBxdWFsaXR5IG9mIHRoZSBwcm9qZWN0ZWQgbWFuaWZlc3QgdmFyaWFibGVzIGlzIGdpdmVuIGJ5IHRoZSAqKkNvc2luZSBzcXVhcmVkKiouIAoKQmVsb3cgeW91IGNhbiBmaW5kIHRoZSBpbnRlcnByZXRhdGlvbiBpbnRlcnZhbHM6CgotIDAuMDAgPCAkQ29zXjIkIDw9IDAuMjU6IExvdyBRdWFsaXR5Ci0gMC4yNSA8ICRDb3NeMiQgPD0gMC41MDogTWVkaXVtLUxvdyBRdWFsaXR5Ci0gMC41MCA8ICRDb3NeMiQgPD0gMC43NTogTWVkaXVtLUhpZ2ggUXVhbGl0eQotIDAuNzUgPCAkQ29zXjIkIDw9IDEuMDA6IEhpZ2ggUXVhbGl0eQoKYGBge3J9CnJvdW5kKHJlcy5wY2ExJHZhciRjb3MyWywxOjJdLDMpCmBgYAoKIyMjIDcuMi4zIFVuaXRzIFBsb3QKCkluIHRoZSB1bml0cyBwbG90IHdlIGNhbiBldmFsdWF0ZSB0aGUgY2x1c3RlcnMgb2YgdW5pdHMuIFRoZSBjbHVzdGVycyBkZWZpbmUgZ3JvdXAgb2YgdW5pdHMgdGhhdCBhcmUgc2ltaWxhciBvbiB0aGUgYmFzaXMgb2YgdGhlIExhdGVudCBWYXJpYWJsZXMgZXN0aW1hdGVkLgoKYGBge3J9CnBsb3QuUENBKHJlcy5wY2ExLCBheGVzID0gYygxLDIpLCBjaG9peCA9ICJpbmQiKQpgYGAKIyMgNy4zIFBDQSB3aXRoIEZhY3RvZXh0cmEgUGFja2FnZQoKYGBge3J9CmxpYnJhcnkoZmFjdG9leHRyYSkKYGBgCgojIyMgNy4zLjEgVmFyaWFibGVzIFBsb3QKCmBgYHtyfQpmdml6X3BjYV92YXIocmVzLnBjYTEpCmBgYAoKIyMjIDcuMy4yIFVuaXRzIFBsb3QKCmBgYHtyfQpmdml6X3BjYV9pbmQocmVzLnBjYTEpCmBgYAoKIyMjIDcuMy4zIEJpUGxvdAoKQmlwbG90IGlzIGEgcGxvdCB3aGVyZSBib3RoIHVuaXRzIGFuZCB2YXJpYWJsZXMgYXJlIHJlcHJlc2VudGVkLgoKYGBge3J9CmZ2aXpfcGNhX2JpcGxvdChyZXMucGNhMSkKYGBgCgojIyA3LjMuNCBHcmFwaGljYWwgcmVwcmVzZW50YXRpb24gb2YgdGhlICoqRWlnZW52YWx1ZXMqKgoKYGBge3J9CmZ2aXpfc2NyZWVwbG90KHJlcy5wY2ExKQpgYGAKCiMjIDcuMy41IEdyYXBoaWNhbCByZXByZXNlbnRhdGlvbiBvZiB0aGUgKipDb250cmlidXRpb25zKiogb2YgdGhlIG1hbmlmZXN0IHZhcmlhYmxlcwoKYGBge3J9CmZ2aXpfcGNhX2NvbnRyaWIocmVzLnBjYTEsIGNob2ljZSA9ICJ2YXIiKQpgYGAKCg==